/*
 * ServerSocketForClient.cpp
 *
 *  Created on: 2013-3-14
 *      Author: song
 */

#include "TcpServer.h"
#include "cmd.h"
#include "IpPort.h"
using namespace std;

void * listen_command(void * param)
{
	TcpServer* pSocket=(TcpServer*)param;
	 cout<<"Enter recv thread!"<<endl;
	 int iClientSockFd=pSocket->m_ClientSockFd;
     while(iClientSockFd>0)
     {

		uint8 buf[1024];
		//int ret=recv(iClientSockFd,(void*)buf,sizeof(buf),0);
		int ret=pSocket->Read(iClientSockFd,(uint8*)buf,sizeof(buf),-1);
		cout<<"ret="<<ret<<endl;

		if(ret<sizeof(Head_t) && ret>0)
			continue;

		ret=pSocket->Write(iClientSockFd,(uint8*)buf,ret);
		continue;



		if(ret==0)//socket断掉
		{
			cout<<"ret==0"<<endl;
			break;
		}

		pSocket->ParseAndAnswerCmd(iClientSockFd,buf,ret);

     }
		close(iClientSockFd);
		cout<<"Exit recv thread!"<<endl;


		pthread_detach(pthread_self());
		return NULL;
}




void * thread_tcp_listen(void * param)
{
		TcpServer* pSocket=(TcpServer*)param;

		//如果之前监听描述符已经存在，取消掉
		if(pSocket->m_ListenSockFd>0)
			close(pSocket->m_ListenSockFd);
		pSocket->m_ListenSockFd=-1;
		pSocket->m_ClientSockFd=-1;

		int sin_size;
		struct sockaddr_in my_addr;    /* 本机地址信息 */
		struct sockaddr_in remote_addr; /* 客户端地址信息 */


		if((pSocket->m_ListenSockFd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
		{
			perror("socket创建出错！");
			return NULL;
		}

		my_addr.sin_family=AF_INET;
		my_addr.sin_port=htons(IpPort::m_PORT_TCP_PLUG_LISTEN);
		my_addr.sin_addr.s_addr = INADDR_ANY;
		bzero(&(my_addr.sin_zero),8);
		int on=1;
		setsockopt(pSocket->m_ListenSockFd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));

		if(bind(pSocket->m_ListenSockFd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
		{
			perror("bind出错！");
			return NULL;
		}

		//同时监听100个链接请求
		if(listen(pSocket->m_ListenSockFd, 100) == -1)
		{
			perror("listen出错！");
			return NULL;
		}

		while(1)
		{

			sin_size = sizeof(struct sockaddr_in);
			if((pSocket->m_ClientSockFd = accept(pSocket->m_ListenSockFd, (struct sockaddr *)&remote_addr,(socklen_t*)&sin_size)) == -1)
			{
				perror("accept");
				return NULL;
			}
			sprintf(pSocket->m_sClientIP,"%s",inet_ntoa(remote_addr.sin_addr));
			cout<<inet_ntoa(remote_addr.sin_addr)<<":"<<ntohs(remote_addr.sin_port)<<endl;


			pthread_t pthRecv;
			pthread_create(&pthRecv,NULL,listen_command,pSocket);


			int keepAlive = 1;
			int keepIdle = 1;
			int keepInterval = 1;
			int keepCount = 1;
			setsockopt(pSocket->m_ClientSockFd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive));
			setsockopt(pSocket->m_ClientSockFd, SOL_TCP,TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle));
			setsockopt(pSocket->m_ClientSockFd, SOL_TCP,TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
			setsockopt(pSocket->m_ClientSockFd,SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
		}

		pthread_detach(pthread_self());
		return NULL;
}

TcpServer::TcpServer()
{
	m_ListenSockFd=-1;
	m_ClientSockFd=-1;
	m_pthServer=-1;

}




/**
 * 发送命令，用于大小端处理
 */
int TcpServer::SendCmd(int fd,uint8 *pBuf,int iLen)
{




	Head_t *phd=(Head_t *)pBuf;
	int iSendLen=phd->len;
	phd->len=htons(phd->len);
	/*
	//no data need to be to the net edian
	switch (phd->byMsgType) {

		case MSG_START_ACK:

			break;


	}
*/
	//reply
	int nwrite=-1;
	nwrite=write(fd,(void*)pBuf,iSendLen);
	return nwrite;

}


/**
 * 解析受到的命令，并处理，并回复
 */

int TcpServer::ParseAndAnswerCmd(int fd,uint8 *pBuf,int iLen)
{

	HValue_t *pV=(HValue_t*)pBuf;
	switch (pV->head.cmd) {


			case MSG_CONFIG_WIFI:
			{
				pV->config_wifi.ssid;
				pV->config_wifi.pswd;
				pV->config_wifi.encryptmethod;

			}
			break;

	}
	//reply
	int nwrite=-1;
	nwrite=write(fd,(void*)pBuf,iLen);
	return nwrite;

}



int TcpServer::StartSvr()
{


	 int ret=ESRCH;
	 if(m_pthServer!=-1)
		ret=pthread_kill(m_pthServer,0);//检测是不是存在


	if(ret==ESRCH)
	{
		pthread_create(&m_pthServer,NULL,thread_tcp_listen,this);
		cout<<"Start server for usr..."<<endl;
		cout<<"Server thread ID:"<<m_pthServer<<endl;
	}
	else
	{
		cout<<"Server is already run!"<<endl;
		cout<<"Server thread ID:"<<m_pthServer<<endl;
		return -1;
	}

    return 0;
}

void TcpServer::StopSvr()
{
	close(m_ClientSockFd);
	close(m_ListenSockFd);
	int ret=ESRCH;
	if(m_pthServer)
	ret=pthread_kill(m_pthServer,0);
	if(ret!=ESRCH)
	{
		pthread_cancel(m_pthServer);
		cout<<"Stop command server."<<endl;
	}

}





int TcpServer::Write(int fd,unsigned char* buf,int len)
{
	int nwrite=-1;
	nwrite=write(fd,(void*)buf,len);
	printf("nwrite=%d\n",nwrite);
	return nwrite;
}

int TcpServer::Read(int fd,unsigned char* buf,int len,double timeout)
{
	 int nread=-1;
	 int ret;
	 fd_set readfds;
	 struct timeval tv;
	 tv.tv_sec=int(timeout);
	 tv.tv_usec=(timeout-int(timeout))*1000000;
	 FD_ZERO(&readfds);
	 FD_SET(fd,&readfds);

	 if(timeout<0)  //涓嶈缃秴鏃舵椂闂?
	 {
		 ret=select(fd+1,&readfds,NULL,NULL,0);
	 }
	 else
		 ret=select(fd+1,&readfds,NULL,NULL,&tv);

	if (ret == -1)
	{
		printf("client socket recv select error.\n");
		return -1;
	}
	else if (ret == 0)
	{
		printf("client socket recv select timeout.\n");
		return -2;
	}
	 if(!FD_ISSET(fd,&readfds))
	 {
		 printf("client socket recv select not from m_fd\n");
		 return -3;
	 }
	 usleep(100000);
	 nread=read(fd,(void *)buf,len);
	 DBG("buf=%s,nread=%d\n",buf,nread);
	 return nread;
}


#if 0


/**
 * 描述：将从网络中收到cmd结构体中的元素值，进行大小端本地化，并验证cmd是否正确
 */
bool TcpServer::CheckCmd(Cmd_t &cmd)
{
	if((cmd.cmd&0xffff) == ((~cmd.rcmd)&0xffff))
		return true;

	return false;
}

/**
 * 描述：将fd和devid绑定，具体方法是使用绑定数组m_devId，下标是fd，值是devid
 */
void TcpServer::BindDevId(int fd,int devId)
{

	int len=sizeof(m_devId)/sizeof(m_devId[0]);
	if(fd<len)
	{
		m_devId[fd]=devId;
	}

}

void TcpServer::DisMap(int len)
{
	int i=0;
	//for(i=0;i<len;i++)
		//DBG("m_devId[%d]=%d \n",i,m_devId[i]);
	{
		DBG("m_devId[0]=%d\n",m_devId[0]);
		DBG("m_devId[1]=%d\n",m_devId[1]);
		DBG("m_devId[2]=%d\n",m_devId[2]);
		DBG("m_devId[3]=%d\n",m_devId[3]);
		DBG("m_devId[4]=%d\n",m_devId[4]);
		DBG("m_devId[5]=%d\n",m_devId[5]);
		DBG("m_devId[6]=%d\n",m_devId[6]);
		DBG("m_devId[7]=%d\n",m_devId[7]);

	}


}
/**
 * 描述：取消fd与devid的绑定
 */
void TcpServer::UnBindDevId(int fd)
{
	int len=sizeof(m_devId)/sizeof(m_devId[0]);
	if(fd<len)
		m_devId[fd]=-1;
}


int TcpServer::GetVctFd(int devId)
{
	DBG("\n");
	int len=sizeof(m_devId)/sizeof(m_devId[0]);
	for(int i=0;i<len;i++)
	{DBG("\n");
		if(devId==m_devId[i])
			m_vctFd.push_back(devId);
	}
	DBG("m_vctFd.size()=\n",m_vctFd.size());
	return m_vctFd.size();

}

/**
 * 描述：从绑定数组中查找值是devid的元素存在与否
 * 允许5个用户同时登录
 * 如果可以绑定，返回true
 */
bool TcpServer::IsCanBind(int devId,int fd)
{
	int len=sizeof(m_devId)/sizeof(m_devId[0]);
	DBG("devId=%d\n",devId);

	//如果是一个新的链接，就允许链接,并且<=5个用户同时登录
	if(fd<len && m_devId[fd]==-1 && GetVctFd(devId)<=5)
		return true;

	return false;
}
/**
 * 描述：从绑定数组中取得index是fd的元素，即相应的devid
 */
int TcpServer::GetDevId(int fd)
{
	int len=sizeof(m_devId)/sizeof(m_devId[0]);
	if(fd<len)
		return m_devId[fd];
	else
		return -1;

}

/**
 * 描述：关闭这条链接
 */
void TcpServer::CloseFd(int fd)
{
	close(fd);
	FD_CLR(fd,&m_readfds);
}

/**
 * 描述：发送一条命令，执行write之前先进行大小端网络化
 */
int TcpServer::SendCmd(int fd,Hu32Value_t &send)
{/*
	send.cmd.rcmd=~send.cmd.cmd;
	send.cmd.cmd=htons(send.cmd.cmd);
	send.cmd.rcmd=htons(send.cmd.rcmd);

	send.value.value=htonl(send.value.value);

	int nwrite=-1;
	nwrite=write(fd,(void*)&send,sizeof(send));
	return nwrite;*/
}

int TcpServer::AnswerErr(int fd,uint16 cmd,int err)
{/*
	Hu32Value_t hValue;
	hValue.cmd.cmd=cmd;
	hValue.value.value=err;
	return SendCmd(fd,hValue);*/
}



int TcpServer::RecCmd(int fd,Cmd_t &cmd)
{
	memset(&cmd,0,sizeof(cmd));
	int len=read(fd,&cmd,sizeof(cmd));
	cmd.cmd=ntohs(cmd.cmd);
	cmd.rcmd=ntohs(cmd.rcmd);

	return len;
}

int TcpServer::RecCmd(int fd,DevInfo_t &devInfo)
{
	memset(&devInfo,0,sizeof(devInfo));
	int len=read(fd,&devInfo,sizeof(devInfo));
	devInfo.devId=ntohl(devInfo.devId);
cout<<devInfo.devId<<endl;
cout<<devInfo.pswd<<endl;

	return len;
}

/**
 * 描述：接收data
 */
int TcpServer::RecCmd(int fd,u32Value_t &value)
{
	memset(&value,0,sizeof(value));
	int len=read(fd,&value,sizeof(value));
	value.value=ntohl(value.value);
	return len;
}


#endif

